﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DataProvider
{
    [Serializable]
    public class SageMethod: SageEntity
    {
        public SageMethod()
        {
        }

        public SageMethod(string file, MethodInfo info, SageVersion version)
            : base()
        {
            Namespace = info.DeclaringType.Namespace;
            Type = info.DeclaringType.Name;
            ReturnType = string.Format("{0}.{1}", info.ReturnType.Namespace, info.ReturnType.Name);
            Name = info.Name;
            Arguments = info.GetParameters().Select(s => new SageArgument(s)).ToList();
            IsProperty = false;
            IsStatic = info.IsStatic;
            IsPublic = info.IsPublic;
            IsProtected = info.IsFamily;
            IsVirtual = info.IsVirtual;
            Assembly = Path.GetFileName(file);
            VersionId = version.Id;
        }

        public SageMethod(string file, PropertyInfo info, SageVersion version)
            : base()
        {
            Namespace = info.DeclaringType.Namespace;
            Type = info.DeclaringType.Name;
            ReturnType = string.Format("{0}.{1}", info.PropertyType.Namespace, info.PropertyType.Name);
            Name = info.Name;
            Arguments = new List<SageArgument>();
            IsProperty = true;
            IsStatic = info.GetOrSetMethod().IsStatic;
            IsPublic = info.GetOrSetMethod().IsPublic;
            IsProtected = info.GetOrSetMethod().IsFamily;
            IsVirtual = info.GetOrSetMethod().IsVirtual;
            Assembly = Path.GetFileName(file);
            VersionId = version.Id;
        }

        public string MethodSignature { get { return string.Format("{0} {1}.{2}::{3}{4}{5}{6}", ReturnType, Namespace, Type, Name, IsProperty? "": "(", IsProperty? "" :  ArgumentsSignature, IsProperty? "": ")"); } }
        
        
        public string ReturnType { get; set; }
        public virtual ICollection<SageArgument> Arguments { get; set; }
        public bool IsProperty { get; set; }

        public string ArgumentsSignature
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                if (Arguments != null)
                {
                    foreach (SageArgument arg in Arguments.OrderBy(s=>s.Name))
                    {
                        sb.Append(arg.Signature);
                        sb.Append(",");
                    }
                    if (sb.Length > 0) sb.Remove(sb.Length - 1, 1);
                }
                return sb.ToString();
            }
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            if (Arguments != null)
            {
                foreach (SageArgument arg in Arguments)
                {
                    sb.Append(arg.ToString());
                    sb.Append(",");
                }
                if (sb.Length > 0) sb.Remove(sb.Length - 1, 1);
            }
            return string.Format("{0} {1}.{2}::{3} ({4})", ReturnType, Namespace, Type, Name, sb);
        }

        public SageMethod Clone()
        {
            return new SageMethod()
            {
                Id = this.Id,
                ReturnType = this.ReturnType,
                IsProperty = this.IsProperty,
                Namespace = this.Namespace,
                Name = this.Name,
                Type = this.Type,
                IsStatic = this.IsStatic,
                IsPublic = this.IsPublic,
                IsProtected = this.IsProtected,
                IsVirtual = this.IsVirtual,
                VersionId = this.VersionId,
                Assembly = this.Assembly,
                Arguments = this.Arguments.Select(s=> s.Clone()).ToList()
            };
        }
    }
}
